#ifndef _PFC_THREADS_H_
#define _PFC_THREADS_H_

namespace pfc
{
    t_size getOptimalWorkerThreadCount();
    t_size getOptimalWorkerThreadCountEx(t_size taskCountLimit);

#ifdef _WINDOWS
    //! IMPORTANT: all classes derived from thread must call waitTillDone() in their destructor, to avoid object destruction during a virtual function call!
    class thread //{{{
    {
    public:
        PFC_DECLARE_EXCEPTION(exception_creation, exception, "Could not create thread");
        thread() : m_thread(INVALID_HANDLE_VALUE) {}
        ~thread()
        {
            PFC_ASSERT(!isActive());
            waitTillDone();
        }
        void start()
        {
            close();
            HANDLE thread;
            const int priority = GetThreadPriority(GetCurrentThread());
            const bool overridePriority = (priority != THREAD_PRIORITY_NORMAL);
            thread = CreateThread(NULL,0,g_entry,reinterpret_cast<void*>(this),overridePriority ? CREATE_SUSPENDED : 0,NULL);
            if (thread == NULL) exception_creation();
            if (overridePriority)
            {
                SetThreadPriority(thread, priority);
                ResumeThread(thread);
            }
            m_thread = thread;
        }
        bool isActive() const
        {
            return m_thread != INVALID_HANDLE_VALUE;
        }
        void waitTillDone()
        {
            close();
        }
    protected:
        virtual void threadProc()
        {
            PFC_ASSERT(!"Stub thread entry - should not get here");
        }
    private:
        void close()
        {
            if (isActive())
            {
                WaitForSingleObject(m_thread,INFINITE);
                CloseHandle(m_thread);
                m_thread = INVALID_HANDLE_VALUE;
            }
        }

        static DWORD CALLBACK g_entry(void* p_instance)
        {
            return reinterpret_cast<thread*>(p_instance)->entry();
        }
        unsigned entry()
        {
            try
            {
                threadProc();
            }
            catch (...) {}
            return 0;
        }
        HANDLE m_thread;

        PFC_CLASS_NOT_COPYABLE_EX(thread)
    };//}}}

#elif defined(__unix)

#include <pthread.h>
//#include <sched.h>

    class thread
    {
    public:
        PFC_DECLARE_EXCEPTION(exception_creation, exception, "Could not create thread");

        thread() : m_thread(NULL) {}
        ~thread()
        {
            PFC_ASSERT(!isActive());
            waitTillDone();
        }

        void start()
        {
            //!关闭或等待之前的线程
            close();

            //获取当前线程的优先级
//            const int priority = GetThreadPriority(GetCurrentThread());
            //判断是否特殊的优先级
//            const bool overridePriority = (priority != THREAD_PRIORITY_NORMAL);
            //创建线程
            pthread_t thread;
//            thread = CreateThread(NULL,0,g_entry,reinterpret_cast<void*>(this),overridePriority ? CREATE_SUSPENDED : 0,NULL);
            int result = pthread_create(&thread,NULL,g_entry,reinterpret_cast<void*>(this));
            if (result != 0) exception_creation();
            //如有必要的话，更新线程的优先级
//            if (overridePriority)
//            {
//                SetThreadPriority(thread, priority);
//                ResumeThread(thread);
//            }
            m_thread = thread;
        }
        bool isActive() const
        {
            return (m_thread != 0);
        }
        void waitTillDone()
        {
            close();
        }
    protected:
        virtual void threadProc()
        {
            PFC_ASSERT(!"Stub thread entry - should not get here");
        }
    private:
        void close()
        {
            if (isActive())
            {
                pthread_join(m_thread,NULL);
                m_thread = NULL;
            }
        }

        static void* g_entry(void* p_instance)
        {
            return reinterpret_cast<thread*>(p_instance)->entry();
        }

        void *entry()
        {
            try
            {
                threadProc();
            }
            catch (...) {}
            return 0;
        }

        pthread_t m_thread;
//        pthread_attr_t attr;
//        sched_param param;

        PFC_CLASS_NOT_COPYABLE_EX(thread)
    };
#else
#error PORTME
#endif
}

#endif //_PFC_THREADS_H_
